home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 2
/
Amiga Tools 2.iso
/
tools
/
jade
/
src
/
amiga_windows.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-09
|
17KB
|
662 lines
/* amiga_windows.c -- Window handling for AmigaDOS
Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
This file is part of Jade.
Jade is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Jade is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jade; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "jade.h"
#include "jade_protos.h"
#include "revision.h"
/* The SET_WRITE_MASK() things needs all this. */
#ifdef _DCC
# define GfxBase_DECLARED
#endif
#include <clib/graphics_protos.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
extern struct GfxBase *GfxBase;
#define INTUI_V36_NAMES_ONLY
#include <clib/intuition_protos.h>
#include <intuition/gadgetclass.h>
#include <clib/diskfont_protos.h>
#include <string.h>
#include <stdlib.h>
_PR int sys_sleep_vw(VW *);
_PR int sys_unsleep_vw(VW *);
_PR void sys_new_vw(VW *);
_PR void sys_kill_vw(VW *);
_PR void sys_update_dimensions(VW *);
_PR void sys_update_scroller(VW *);
_PR struct Window *sys_new_window(VW *, VW *, bool);
_PR void sys_kill_window(VW *);
static void close_shared_window(struct Window *);
static void strip_intui_messages(struct MsgPort *, struct Window *);
_PR struct IntuiMessage *ami_get_win_imsg(struct Window *);
_PR void sys_activate_win(VW *);
_PR void sys_set_vw_pos(VW *, long, long, long, long);
_PR int ami_ezreq(u_char *, u_char *, long, ...);
_PR int sys_set_font(VW *);
_PR void sys_unset_font(VW *);
_PR void sys_reset_sleep_titles(TX *);
_PR bool sys_get_mouse_pos(POS *, VW *);
_PR void sys_windows_init(void);
#define IDCMP (IDCMP_NEWSIZE | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE \
| IDCMP_MENUPICK | IDCMP_CLOSEWINDOW | IDCMP_RAWKEY \
| IDCMP_ACTIVEWINDOW | IDCMP_GADGETUP | IDCMP_GADGETUP \
| IDCMP_INTUITICKS)
#define SIDCMP (IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY | IDCMP_INTUITICKS)
#define WFLAGS (WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET \
| WFLG_SIZEGADGET | WFLG_REPORTMOUSE | WFLG_ACTIVATE | WFLG_RMBTRAP \
| WFLG_SMART_REFRESH | WFLG_NOCAREREFRESH)
#define SWFLAGS (WFLG_DRAGBAR | WFLG_ACTIVATE \
| WFLG_SMART_REFRESH | WFLG_NOCAREREFRESH | WFLG_RMBTRAP)
static const u_char *window_title = VERSSTRING;
static struct MsgPort *shared_window_port;
#ifdef AMIGA_NEED_VARARGS_STUBS
ULONG
SetGadgetAttrs(struct Gadget *gadget, struct Window *window, struct Requester *req, unsigned long tag1, ...)
{
return(SetGadgetAttrsA(gadget, window, req, (struct TagItem *)&tag1));
}
APTR
NewObject(struct IClass *class, UBYTE *classID, unsigned long tag1, ...)
{
return(NewObjectA(class, classID, (struct TagItem *)&tag1));
}
#endif /* AMIGA_NEEDS_VARARGS_STUBS */
/*
* Have I screwed this up??
*/
int
sys_sleep_vw(VW *vw)
{
int rc = FALSE;
struct Window *swin;
if(swin = OpenWindowTags(NULL,
WA_Left, vw->vw_Window->LeftEdge,
WA_Top, vw->vw_Window->TopEdge,
WA_Width, 150,
WA_Height, vw->vw_Window->BorderTop,
WA_IDCMP, 0,
WA_Flags, SWFLAGS,
WA_Title, VSTR(vw->vw_Tx->tx_BufferName),
WA_AutoAdjust, TRUE,
WA_PubScreenName, VSTR(vw->vw_WindowSys.ws_ScreenName),
WA_PubScreenFallBack, TRUE,
TAG_END))
{
swin->UserPort = shared_window_port;
ModifyIDCMP(swin, SIDCMP);
vw->vw_WindowSys.ws_OldDimensions[0] = vw->vw_Window->LeftEdge;
vw->vw_WindowSys.ws_OldDimensions[1] = vw->vw_Window->TopEdge;
vw->vw_WindowSys.ws_OldDimensions[2] = vw->vw_Window->Width;
vw->vw_WindowSys.ws_OldDimensions[3] = vw->vw_Window->Height;
ami_clear_menu(vw->vw_Window);
Forbid();
strip_intui_messages(vw->vw_Window->UserPort, vw->vw_Window);
vw->vw_Window->UserPort = NULL;
ModifyIDCMP(vw->vw_Window, 0L);
Permit();
CloseWindow(vw->vw_Window);
#ifndef NOSCRLBAR
if(((vw->vw_Flags & VWFF_SLEEPING) == 0) && vw->vw_SBar.gad)
{
DisposeObject(vw->vw_SBar.gad);
vw->vw_SBar.gad = NULL;
}
#endif
vw->vw_Window = swin;
vw->vw_WindowSys.ws_Rp = swin->RPort;
vw->vw_Flags |= VWFF_SLEEPING;
swin->UserData = (BYTE *)vw;
rc = TRUE;
}
else
cmd_signal(sym_error, LIST_1(MKSTR("Can't open window")));
return(rc);
}
int
sys_unsleep_vw(VW *vw)
{
int rc = TRUE;
if(vw->vw_Flags & VWFF_SLEEPING)
{
struct Window *oldwin = vw->vw_Window;
if(sys_new_window(vw, vw, FALSE))
{
Forbid();
strip_intui_messages(oldwin->UserPort, oldwin);
oldwin->UserPort = NULL;
ModifyIDCMP(oldwin, 0L);
Permit();
CloseWindow(oldwin);
vw->vw_Flags &= ~VWFF_MESSAGE;
sys_update_dimensions(vw);
#ifndef NOSCRLBAR
sys_update_scroller(vw);
#endif
vw->vw_Flags |= VWFF_FORCE_REFRESH;
}
else
rc = FALSE;
}
return(rc);
}
void
sys_new_vw(VW *vw)
{
}
void
sys_kill_vw(VW *vw)
{
}
void
sys_update_dimensions(VW *vw)
{
if(vw->vw_Window && ((vw->vw_Flags & VWFF_SLEEPING) == 0))
{
struct Window *wd = vw->vw_Window;
vw->vw_MessageLineY = wd->Height - wd->BorderBottom
- vw->vw_FontY - 2;
vw->vw_MessageFontY = vw->vw_MessageLineY + 2 + FONT_ASCENT(vw);
vw->vw_XStartPix = (UWORD)wd->BorderLeft;
vw->vw_YStartPix = (UWORD)wd->BorderTop;
vw->vw_XEndPix = wd->Width - (UWORD)wd->BorderRight - 1;
vw->vw_YEndPix = (vw->vw_MessageLineY - 1);
vw->vw_XWidthPix = vw->vw_XEndPix - vw->vw_XStartPix;
vw->vw_YHeightPix = vw->vw_YEndPix - vw->vw_YStartPix;
vw->vw_FontStart = vw->vw_YStartPix + vw->vw_Font->tf_Baseline;
vw->vw_MaxX = (vw->vw_XWidthPix / vw->vw_FontX);
vw->vw_MaxY = (vw->vw_YHeightPix / vw->vw_FontY);
if((vw->vw_XStepRatio <= 0)
|| ((vw->vw_XStep = vw->vw_MaxX / vw->vw_XStepRatio) <= 0))
vw->vw_XStep = 1;
if((vw->vw_YStepRatio <= 0)
|| ((vw->vw_YStep = vw->vw_MaxY / vw->vw_YStepRatio) <= 0))
vw->vw_YStep = 1;
}
}
#ifndef NOSCRLBAR
void
sys_update_scroller(VW *vw)
{
if(((vw->vw_Flags & VWFF_SLEEPING) == 0) && vw->vw_SBar.gad)
{
vw->vw_SBar.top = vw->vw_StartLine;
vw->vw_SBar.total = vw->vw_Tx->tx_NumLines;
SetGadgetAttrs(vw->vw_SBar.gad, vw->vw_Window, NULL,
PGA_Visible, vw->vw_MaxY,
PGA_Total, vw->vw_SBar.total,
PGA_Top, vw->vw_SBar.top,
TAG_END);
}
}
#endif
/*
* Opens an editor window. Sets up the shared IDCMP
*/
struct Window *
sys_new_window(VW *oldVW, VW *vw, bool useDefDims)
{
u_short *dimensions;
struct Screen *scr;
struct Window *res = NULL;
bool truedims = FALSE;
if(!useDefDims && oldVW)
{
if(oldVW->vw_Flags & VWFF_SLEEPING)
dimensions = oldVW->vw_WindowSys.ws_OldDimensions;
else
dimensions = &oldVW->vw_Window->LeftEdge;
truedims = TRUE;
}
else
dimensions = def_dims;
if(scr = LockPubScreen(*VSTR(vw->vw_WindowSys.ws_ScreenName)
? VSTR(vw->vw_WindowSys.ws_ScreenName)
: NULL))
{
#ifndef NOSCRLBAR
if(vw->vw_SBar.gad = NewObject(NULL, "propgclass",
GA_RelRight, -13,
GA_Top, 1 + scr->WBorTop + scr->Font->ta_YSize + 1,
GA_Width, 10,
GA_RelHeight, -12 - (scr->WBorTop + scr->Font->ta_YSize + 1),
GA_RelVerify, TRUE,
GA_Immediate, TRUE,
GA_FollowMouse, TRUE,
GA_RightBorder, TRUE,
PGA_Borderless, TRUE,
PGA_Freedom, FREEVERT,
PGA_Total, 1,
PGA_Visible, 1,
PGA_Top, 0,
PGA_NewLook, TRUE,
TAG_END))
{
#endif
if(res = OpenWindowTags(NULL,
WA_Left, dimensions[0],
WA_Top, dimensions[1],
WA_InnerWidth, truedims ? dimensions[2] : (dimensions[2] * vw->vw_FontX + 1),
WA_InnerHeight, truedims ? dimensions[3] : (dimensions[3] + 1) * vw->vw_FontY + 3,
WA_IDCMP, shared_window_port ? 0 : IDCMP,
WA_MinWidth, 80,
WA_MinHeight, 40,
WA_MaxWidth, ~0,
WA_MaxHeight, ~0,
#if AMIGA_INCLUDE_VER >= 39
WA_Flags, WFLAGS | WFLG_NEWLOOKMENUS,
#else
WA_Flags, WFLAGS,
#endif
#ifndef NOSCRLBAR
WA_Gadgets, vw->vw_SBar.gad,
#endif
WA_Title, window_title,
WA_AutoAdjust, TRUE,
WA_PubScreen, scr,
WA_RptQueue, 2,
TAG_END))
{
if(shared_window_port)
{
res->UserPort = shared_window_port;
ModifyIDCMP(res, IDCMP);
}
else
shared_window_port = res->UserPort;
vw->vw_Window = res;
ami_set_menu(res);
vw->vw_WindowSys.ws_Rp = res->RPort;
res->UserData = (BYTE *)vw;
SetFont(vw->vw_WindowSys.ws_Rp, vw->vw_Font);
SET_WRITE_MASK(vw->vw_WindowSys.ws_Rp, 1);
}
#ifndef NOSCRLBAR
else
DisposeObject(vw->vw_SBar.gad);
}
#endif
UnlockPubScreen(NULL, scr);
}
return(res);
}
void
sys_kill_window(VW *vw)
{
ami_clear_menu(vw->vw_Window);
close_shared_window(vw->vw_Window);
#ifndef NOSCRLBAR
if(((vw->vw_Flags & VWFF_SLEEPING) == 0) && vw->vw_SBar.gad)
{
DisposeObject(vw->vw_SBar.gad);
vw->vw_SBar.gad = NULL;
}
#endif
}
/*
* Code to close a window who's sharing a UserPort -- taken from
* CloseWindow() autodoc.
*/
static void
close_shared_window(struct Window *win)
{
ami_clear_menu(win);
if(window_count > 1)
{
Forbid();
strip_intui_messages(win->UserPort, win);
win->UserPort = NULL;
ModifyIDCMP(win, 0L);
Permit();
}
else
shared_window_port = NULL;
CloseWindow(win);
}
static void
strip_intui_messages(struct MsgPort *mp, struct Window *win)
{
struct IntuiMessage *msg;
struct Node *succ;
msg = (struct IntuiMessage *)mp->mp_MsgList.lh_Head;
while(succ = msg->ExecMessage.mn_Node.ln_Succ)
{
if(msg->IDCMPWindow == win)
{
Remove((struct Node *)msg);
ReplyMsg((struct Message *)msg);
}
msg = (struct IntuiMessage *)succ;
}
}
/*
* Gets the next Imsg for the specified window -- this is used for event
* loops local to a single window
*/
struct IntuiMessage *
ami_get_win_imsg(struct Window *win)
{
struct IntuiMessage *msg;
struct Node *succ;
Forbid();
msg = (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
while(succ = msg->ExecMessage.mn_Node.ln_Succ)
{
if(msg->IDCMPWindow == win)
{
Remove((struct Node *)msg);
Permit();
return(msg);
}
msg = (struct IntuiMessage *)succ;
}
Permit();
return(FALSE);
}
void
sys_activate_win(VW *vw)
{
WindowToFront(vw->vw_Window);
ActivateWindow(vw->vw_Window);
}
void
sys_set_vw_pos(VW *vw, long x, long y, long w, long h)
{
if(vw->vw_Flags & VWFF_SLEEPING)
{
vw->vw_WindowSys.ws_OldDimensions[0] = x;
vw->vw_WindowSys.ws_OldDimensions[1] = y;
vw->vw_WindowSys.ws_OldDimensions[2] = w;
vw->vw_WindowSys.ws_OldDimensions[3] = h;
}
else
{
ChangeWindowBox(vw->vw_Window, x, y, w, h);
vw->vw_DeferRefresh = 1;
}
}
static struct EasyStruct ezstruct =
{
sizeof(struct EasyStruct),
0,
"Jade request...",
NULL,
NULL,
};
int
ami_ezreq(u_char *bodyFmt, u_char *gadFmt, long arg1, ...)
{
ezstruct.es_TextFormat = bodyFmt;
ezstruct.es_GadgetFormat = gadFmt;
return(EasyRequestArgs(curr_vw->vw_Window, &ezstruct, NULL, &arg1));
}
_PR VALUE cmd_req(VALUE body, VALUE gads);
DEFUN("req", cmd_req, subr_req, (VALUE body, VALUE gads), V_Subr2, DOC_req) /*
::doc:req::
req BODY-STRING GADGETS-STRING
<AMIGA-ONLY>
Function to do a request.
Result is number of gadget pressed (starting at 1 for leftmost gadget and
incrementing by one, rightmost gadget is 0.
::end:: */
{
DECLARE1(body, STRINGP);
DECLARE2(gads, STRINGP);
return(make_number(ami_ezreq(VSTR(body), VSTR(gads), 0)));
}
int
sys_set_font(VW *vw)
{
struct TextAttr ta;
struct TextFont *tf;
ta.ta_Name = VSTR(vw->vw_FontName);
ta.ta_YSize = vw->vw_WindowSys.ws_FontSize;
ta.ta_Style = FS_NORMAL;
ta.ta_Flags = 0;
if(tf = OpenDiskFont(&ta))
{
if(tf->tf_Flags & FPF_PROPORTIONAL)
{
CloseFont(tf);
return(FALSE);
}
if(vw->vw_Font)
CloseFont(vw->vw_Font);
vw->vw_Font = tf;
vw->vw_FontX = vw->vw_Font->tf_XSize;
vw->vw_FontY = vw->vw_Font->tf_YSize;
if(vw->vw_Window)
{
SetFont(vw->vw_WindowSys.ws_Rp, tf);
sys_update_dimensions(vw);
}
return(TRUE);
}
return(FALSE);
}
void
sys_unset_font(VW *vw)
{
if(vw->vw_Font)
{
CloseFont(vw->vw_Font);
vw->vw_Font = NULL;
}
}
_PR VALUE cmd_set_font(VALUE font, VALUE vw);
DEFUN_INT("set-font", cmd_set_font, subr_set_font, (VALUE font, VALUE vw), V_Subr2, DOC_set_font, "sFont name (`FONT_NAME-SIZE'): ")
{
VALUE oldfont, newfont;
LONG oldsize, newsize;
u_char *tmp;
DECLARE1(font, STRINGP);
if(!WINDOWP(vw))
vw = VAL(curr_vw);
oldfont = VWIN(vw)->vw_FontName;
oldsize = VWIN(vw)->vw_WindowSys.ws_FontSize;
tmp = strrchr(VSTR(font), '-');
if(!tmp)
return(cmd_signal(sym_error, list_2(MKSTR("No font-size specified"),
font)));
newsize = atol(tmp+1);
newfont = string_dupn(VSTR(font), tmp - VSTR(font));
VWIN(vw)->vw_WindowSys.ws_FontSize = newsize;
VWIN(vw)->vw_FontName = newfont;
if(sys_set_font(VWIN(vw)))
{
VWIN(vw)->vw_Flags |= VWFF_FORCE_REFRESH;
return(sym_t);
}
else
{
cmd_signal(sym_error, list_2(MKSTR("Can't open font"), font));
VWIN(vw)->vw_FontName = oldfont;
VWIN(vw)->vw_WindowSys.ws_FontSize = oldsize;
return(NULL);
}
}
_PR VALUE var_pub_screen(VALUE val);
DEFUN("pub-screen", var_pub_screen, subr_pub_screen, (VALUE val), V_Var, DOC_pub_screen) /*
::doc:pub_screen::
This variable controls the name of the public-screen which the window
opens onto. It is only available when running on an Amiga.
::end:: */
{
VW *vw = curr_vw;
if(val)
{
if(STRINGP(val))
vw->vw_WindowSys.ws_ScreenName = val;
return(val);
}
else
return(vw->vw_WindowSys.ws_ScreenName);
}
/*
* Used when the name of a TX is changed. All sleeping views have their title
* display updated.
*/
void
sys_reset_sleep_titles(TX *tx)
{
VW *vw = view_chain;
while(vw)
{
if(vw->vw_Window && (vw->vw_Tx == tx)
&& (vw->vw_Flags & VWFF_SLEEPING))
{
SetWindowTitles(vw->vw_Window, VSTR(tx->tx_BufferName),
(UBYTE *)~0);
}
vw = vw->vw_Next;
}
}
_PR VALUE cmd_screen_width(void);
DEFUN("screen-width", cmd_screen_width, subr_screen_width, (void), V_Subr0, DOC_screen_width)
{
return(make_number(curr_vw->vw_Window->WScreen->Width));
}
_PR VALUE cmd_screen_height(void);
DEFUN("screen-height", cmd_screen_height, subr_screen_height, (void), V_Subr0, DOC_screen_height)
{
return(make_number(curr_vw->vw_Window->WScreen->Height));
}
_PR VALUE cmd_window_left_edge(void);
DEFUN("window-left-edge", cmd_window_left_edge, subr_window_left_edge, (void), V_Subr0, DOC_window_left_edge)
{
return(make_number(curr_vw->vw_Window->LeftEdge));
}
_PR VALUE cmd_window_top_edge(void);
DEFUN("window-top-edge", cmd_window_top_edge, subr_window_top_edge, (void), V_Subr0, DOC_window_top_edge)
{
return(make_number(curr_vw->vw_Window->TopEdge));
}
_PR VALUE cmd_window_width(void);
DEFUN("window-width", cmd_window_width, subr_window_width, (void), V_Subr0, DOC_window_width)
{
return(make_number(curr_vw->vw_Window->Width));
}
_PR VALUE cmd_window_height(void);
DEFUN("window-height", cmd_window_height, subr_window_height, (void), V_Subr0, DOC_window_height)
{
return(make_number(curr_vw->vw_Window->Height));
}
_PR VALUE cmd_window_bar_height(void);
DEFUN("window-bar-heigth", cmd_window_bar_height, subr_window_bar_height, (void), V_Subr0, DOC_window_bar_height)
{
return(make_number((LONG)curr_vw->vw_Window->BorderTop));
}
bool
sys_get_mouse_pos(POS *res, VW *vw)
{
struct Window *wd = vw->vw_Window;
WORD x = wd->MouseX;
WORD y = wd->MouseY;
if(((x < wd->Width) && (x > (wd->Width - wd->BorderRight)))
|| ((y > 0) && (y < wd->BorderTop)))
{
*res = vw->vw_CursorPos;
return(TRUE);
}
if(x >= wd->Width)
res->pos_Col = vw->vw_StartCol + vw->vw_MaxX + 1;
else if(x <= 0)
res->pos_Col = vw->vw_StartCol - 1;
else if(x < (wd->Width - wd->BorderRight))
res->pos_Col = vw->vw_StartCol + ((x - (WORD)vw->vw_XStartPix) / (WORD)vw->vw_FontX);
if(y >= wd->Height)
res->pos_Line = vw->vw_StartLine + vw->vw_MaxY;
else if(y <= 0)
res->pos_Line = vw->vw_StartLine - 1;
else if(y > wd->BorderTop)
res->pos_Line = vw->vw_StartLine + ((y - (WORD)vw->vw_YStartPix) / (WORD)vw->vw_FontY);
if(res->pos_Col < 0)
res->pos_Col = 0;
if(res->pos_Line < 0)
res->pos_Line = 0;
if(res->pos_Line >= vw->vw_Tx->tx_NumLines)
res->pos_Line = vw->vw_Tx->tx_NumLines - 1;
res->pos_Col = char_col(vw->vw_Tx, res->pos_Col, res->pos_Line);
return(TRUE);
}
void
sys_windows_init(void)
{
ADD_SUBR(subr_req);
ADD_SUBR(subr_set_font);
ADD_SUBR(subr_pub_screen);
ADD_SUBR(subr_screen_width);
ADD_SUBR(subr_screen_height);
ADD_SUBR(subr_window_left_edge);
ADD_SUBR(subr_window_top_edge);
ADD_SUBR(subr_window_width);
ADD_SUBR(subr_window_height);
ADD_SUBR(subr_window_bar_height);
}